package eteam.aps.systemservice.bll;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import eteam.aps.common.QueryResult;
import eteam.aps.common.enumeration.SortEnum;
import eteam.aps.common.exceptions.BusinessException;
import eteam.aps.common.helper.Helper;
import eteam.aps.systeminterface.model.dto.RoleDto;
import eteam.aps.systeminterface.model.dto.VerifyTokenDto;
import eteam.aps.systeminterface.model.entity.FunaclEntity;
import eteam.aps.systeminterface.model.entity.GroupuserEntity;
import eteam.aps.systeminterface.model.entity.ModuleoperEntity;
import eteam.aps.systeminterface.model.entity.UserEntity;
import eteam.aps.systeminterface.model.enums.OrgTypeEnum;
import eteam.aps.systeminterface.model.enums.PersonTypeEnum;
import eteam.aps.systeminterface.model.enums.StateEnum;
import eteam.aps.systeminterface.model.reqparam.QueryRoleParam;
import eteam.aps.systeminterface.model.reqparam.UserRoleParam;
import eteam.aps.systemservice.dal.FunaclDal;
import eteam.aps.systemservice.dal.GroupuserDal;
import eteam.aps.systemservice.dal.ModuleoperDal;
import eteam.aps.systemservice.dal.UserDal;
import eteam.aps.systemservice.model.mapper.IRoleMapper;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 角色相关业务
 */
@Service
public class RoleBll {
    @Autowired
    private UserDal userDal;
    @Autowired
    private ModuleoperDal moduleoperDal;
    @Autowired
    private FunaclDal funaclDal;
    @Autowired
    private GroupuserDal groupuserDal;

    /**
     * 分页查询角色列表
     *
     * @param queryParam
     * @return
     */
    public QueryResult<UserEntity> queryRolePageList(QueryRoleParam queryParam) throws Exception {
        IPage<UserEntity> page = new Page<UserEntity>(queryParam.getPageIndex(), queryParam.getPageSize());
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<UserEntity>();
        if (queryParam.getState() > StateEnum.Delete.getValue()) {
            wrapper.eq("State", queryParam.getState());
        } else {
            wrapper.ne("State", StateEnum.Delete.getValue());
        }
        if (StringUtils.isNotBlank(queryParam.getKeyword())) {
            wrapper.and(i -> i.like("FUserName", queryParam.getKeyword()).or().like("FFullName", queryParam.getKeyword()));
        }
        if (StringUtils.isNotBlank(queryParam.getSortFields()) && queryParam.getSortOrder().equals(SortEnum.Asc)) {
            wrapper.orderByAsc(queryParam.getSortFields());
        } else if (StringUtils.isNotBlank(queryParam.getSortFields()) && queryParam.getSortOrder().equals(SortEnum.Desc)) {
            wrapper.orderByDesc(queryParam.getSortFields());
        } else {
            wrapper.orderByAsc("FUserName");
        }
        page = userDal.queryRolePageList(page, wrapper);
        QueryResult<UserEntity> result = new QueryResult<UserEntity>(Math.toIntExact(page.getTotal()), page.getRecords());
        return result;
    }

    /**
     * 创建角色
     *
     * @param roleDto: 请求参数
     * @throws Exception
     */
    public void createRole(VerifyTokenDto tokenDto, RoleDto roleDto) throws Exception {
        UserEntity roleEntity = IRoleMapper.INSTANCE.toEntity(roleDto);
        roleEntity.setFuserid(Helper.GetId());
        roleEntity.setFpersontype(PersonTypeEnum.Role.getValue());
        roleEntity.setFcreator(tokenDto.getFuserid());
        roleEntity.setFcreatorname(tokenDto.getFfullname());
        roleEntity.setFcreatetime(DateUtil.date());
        roleEntity.setFtimestamp(DateUtil.date());
        roleEntity.setState(StateEnum.Enable.getValue());
        int count = userDal.insertData(roleEntity);
        if (count < 1) {
            throw new BusinessException("创建角色失败");
        }
    }

    /**
     * 更新角色
     *
     * @param roleDto: 请求参数
     * @throws Exception
     */
    public void updateRole(VerifyTokenDto tokenDto, RoleDto roleDto) throws Exception {
        UserEntity roleEntity = IRoleMapper.INSTANCE.toEntity(roleDto);
        roleEntity.setFlastmodifier(tokenDto.getFuserid());
        roleEntity.setFlastmodifiername(tokenDto.getFfullname());
        roleEntity.setFlastmodifytime(DateUtil.date());
        int count = userDal.updateData(roleEntity);
        if (count < 1) {
            throw new BusinessException("更新角色失败");
        }
    }

    /**
     * 删除角色
     *
     * @param roleId: 角色ID
     * @throws Exception
     */
    public void deleteRole(String roleId) throws Exception {
        UserEntity retObj = userDal.getUserById(roleId);
        if (Objects.isNull(retObj)) {
            throw new BusinessException("角色不存在");
        }
        if (retObj.getFusername().equals("Administrators") || retObj.getFusername().equals("AppUser")) {
            throw new BusinessException("内置角色，不允许删除");
        }
        UserEntity tmpObj = new UserEntity();
        tmpObj.setFuserid(roleId);
        tmpObj.setFusername(StrUtil.format("{}_{}", retObj.getFusername(), System.currentTimeMillis()));
        tmpObj.setState(StateEnum.Delete.getValue());
        int count = userDal.updateData(tmpObj);
        if (count < 1) {
            throw new BusinessException("删除角色失败");
        }
    }

    /**
     * 改变角色状态
     *
     * @param roleId:    角色ID
     * @param stateEnum: 状态
     * @throws Exception
     */
    public void changeState(String roleId, StateEnum stateEnum) throws Exception {
        UserEntity tmpObj = new UserEntity();
        tmpObj.setFuserid(roleId);
        tmpObj.setState(stateEnum.getValue());
        int count = userDal.updateData(tmpObj);
        if (count < 1) {
            throw new BusinessException("改变角色状态失败");
        }
    }

    /**
     * 根据角色ID获取用例列表
     *
     * @param roleId
     * @return
     * @throws Exception
     */
    public List<ModuleoperEntity> getUcByRoleId(String roleId) throws Exception {
        return moduleoperDal.getListByRoleId(roleId);
    }

    /**
     * 设置角色用例
     *
     * @param roleId
     * @return
     * @throws Exception
     */
    public void setRoleUc(String roleId, List<String> ucList) throws Exception {
        funaclDal.deleteByRoleId(roleId);
        List<FunaclEntity> tmpList = new ArrayList<FunaclEntity>();
        for (String uckey : ucList) {
            FunaclEntity item = new FunaclEntity();
            item.setFaclid(Helper.GetId());
            item.setFuserid(roleId);
            item.setFoperation(uckey);
            tmpList.add(item);
        }
        funaclDal.createFunacl(tmpList);
    }

    /**
     * 根据适用类型获取角色列表
     *
     * @param userRoleParam
     * @return
     */
    public List<UserEntity> getRoleListByType(UserRoleParam userRoleParam) throws Exception {
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<UserEntity>();
        wrapper.eq("FPersonType", PersonTypeEnum.Role.getValue());
        wrapper.eq("State", StateEnum.Enable.getValue());
        wrapper.and(p -> p.eq("FGroupOrgId", userRoleParam.getOrgid()).or().eq("FUnitTypeId", userRoleParam.getType()));
        wrapper.orderByDesc("FCreateTime");
        return userDal.getListByWrapper(wrapper);
    }

    /**
     * 获取角色列表
     * 需求变更004，不需要控制角色适用范围
     *
     * @return
     */
    public List<UserEntity> getRoleList() throws Exception {
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<UserEntity>();
        wrapper.eq("FPersonType", PersonTypeEnum.Role.getValue());
        wrapper.eq("State", StateEnum.Enable.getValue());
        wrapper.orderByAsc("FCreateTime");
        return userDal.getListByWrapper(wrapper);
    }

    /**
     * 根据用户ID获取角色列表
     *
     * @param userId
     * @return
     */
    public List<UserEntity> getRoleListByUserId(String userId) throws Exception {
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<UserEntity>();
        wrapper.eq("FPersonType", PersonTypeEnum.Role.getValue());
        //wrapper.eq("State", StateEnum.Enable.getValue());
        wrapper.inSql("FUserId", String.format("select distinct FGroupId from sp_groupuser where FUserId='%s'", userId));
        wrapper.orderByDesc("FCreateTime");
        return userDal.getListByWrapper(wrapper);
    }

    /**
     * 设置角色用户
     *
     * @param userId
     * @return
     * @throws Exception
     */
    public void setRoleUser(String userId, List<String> roleIds) throws Exception {
        groupuserDal.deleteByUserId(userId);
        List<GroupuserEntity> tmpList = new ArrayList<GroupuserEntity>();
        for (String key : roleIds) {
            GroupuserEntity item = new GroupuserEntity();
            item.setFuserid(userId);
            item.setFgroupid(key);
            tmpList.add(item);
        }
        groupuserDal.createGroupuser(tmpList);
    }

    /**
     * 用户是否属于某个角色
     *
     * @param userId:   用户ID
     * @param roleName: 角色名
     * @return
     */
    public Boolean userHasRole(String userId, String roleName) {
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<UserEntity>();
        wrapper.eq("FPersonType", PersonTypeEnum.Role.getValue());
        wrapper.eq("FFullName", roleName);
        wrapper.inSql("FUserId", String.format("select distinct FGroupId from sp_groupuser where FUserId='%s'", userId));
        return userDal.getCountByWrapper(wrapper) > 0;
    }

    /**
     * 获取所有角色名称列表
     *
     * @return: 角色名称列表
     */
    public List<String> getRoleNameList() {
        return userDal.getRoleNameList();
    }

    /**
     * 根据机构类型获取角色名称列表
     *
     * @param orgType: 机构类型
     * @return: 角色名称列表
     */
    public List<String> getRoleNameListByType(OrgTypeEnum orgType) {
        return userDal.getRoleNameListByType(orgType);
    }
}
